extends Camera3D

var point_of_interest# к чему привязать камеру
var choose = true # привязать или отвязать камеру
var right_click_mode: bool= false

@export var enabled = true: set = set_enabled
@export var mouse_mode = 2 # (int, "Visible", "Hidden", "Captured, Confined")

# Freelook settings
@export var freelook = true
@export (float, 0.0, 1.0) var sensitivity = 0.5
@export (float, 0.0, 0.999, 0.001) var smoothness = 0.5: set = set_smoothness
@export (int, 0, 360) var yaw_limit = 360
@export (int, 0, 360) var pitch_limit = 360

# Pivot Settings
@export var privot: NodePath: set = set_privot
@export var rotate_privot = false
var distance =25.0
var distance_smooth
@export var distance_min = 10
@export var distance_max = 100
@export var distance_step: float = 2.0

# Movement settings
@export (float, 0.0, 1.0) var acceleration = 0.1
@export (float, 0.0, 0.0, 1.0) var deceleration = 0.1
@export var max_speed = Vector3(100.0, 100.0, 100.0)
@export var local = true

# Intern variables.
var _mouse_offset = Vector2()
var _rotation_offset = Vector2()
var _yaw = 0.0
var _pitch = 0.0
var _total_yaw = 0.0
var _total_pitch = 0.0

var _direction = Vector3(0.0, 0.0, 0.0)
var _speed = Vector3(0.0, 0.0, 0.0)

const ROTATION_MULTIPLIER = 500
func _ready():
	# Управление камерой при RU раскладке клав.
	var event = InputEventKey.new()
	var a = ord ("ф")
	var w = ord ("ц")
	var s = ord ("ы")
	var d = ord ("в")
	event.unicode = a
	event.unicode = w
	event.unicode = s
	event.unicode = d
	#
	Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)

#func _input(event):
func _unhandled_input(event):
	if freelook:
		if Input.is_action_just_pressed("right_click"):
			right_click_mode = true;
			Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
		if Input.is_action_just_released("right_click"):
			right_click_mode = false;
			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
		if right_click_mode:
			if event is InputEventMouseMotion:
				_mouse_offset = event.relative
			
					
	if Input.is_action_just_pressed("ui_select"):
		choose=!choose
		if choose:
			set_privot(point_of_interest)
		else:
			set_privot(null)

	if privot:
		if event.is_action_pressed("wheel_down"):
			distance-=distance_step
		if event.is_action_pressed("wheel_up"):
			distance += distance_step


func _physics_process(delta):
	collide()
	if privot:
		distance += (Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")) * distance_step * 0.1
		distance = clamp(distance,distance_min,distance_max)
		distance_smooth =lerp(distance_smooth,distance,0.05)
		set_position(privot.get_position())
		translate_object_local(Vector3(0.0, 0.0, distance_smooth))
	else:
		_update_movement(delta)
	if freelook:
		_update_rotation(delta)


func collide():
	if privot:
		if $down.is_colliding():
			_mouse_offset.y = 1
		if $up.is_colliding():
			_mouse_offset.y = -1
		if $left.is_colliding():
			_mouse_offset.x = 1
		if $right.is_colliding():
			_mouse_offset.x = -1
		if $forward.is_colliding():
			distance +=distance_step 
		if $back.is_colliding():
			distance -=distance_step 
	else:
		if $down.is_colliding():
			_direction.y = 2
		if $up.is_colliding():
			_direction.y = -2
		if $left.is_colliding():
			_direction.x = 2
		if $right.is_colliding():
			_direction.x = -2
		if $forward.is_colliding():
			_direction.z =2 
		if $back.is_colliding():
			_direction.z =-2 


func _update_movement(delta):
	if !privot:
		_direction.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
		_direction.y = Input.get_action_strength("ui_page_up") - Input.get_action_strength("ui_page_down")
		_direction.z = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
	else:
		_direction = Vector3.ZERO
	var offset = max_speed * acceleration * _direction

	_speed.x = clamp(_speed.x + offset.x, -max_speed.x, max_speed.x)
	_speed.y = clamp(_speed.y + offset.y, -max_speed.y, max_speed.y)
	_speed.z = clamp(_speed.z + offset.z, -max_speed.z, max_speed.z)

	# Apply deceleration if no input
	if _direction.x == 0:
		_speed.x *= (1.0 - deceleration)
	if _direction.y == 0:
		_speed.y *= (1.0 - deceleration)
	if _direction.z == 0:
		_speed.z *= (1.0 - deceleration)

	if local:
		translate_object_local(_speed * delta)
	else:
		global_translate(_speed * delta)


# warning-ignore:unused_argument
func _update_rotation(delta):
	if privot:
		_mouse_offset.x -= Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
		_mouse_offset.y += Input.get_action_strength("ui_page_up") - Input.get_action_strength("ui_page_down")
	var offset = Vector2();
	offset += _mouse_offset * sensitivity
	_mouse_offset = Vector2()
	_yaw = _yaw * smoothness + offset.x * (1.0 - smoothness)
	_pitch = _pitch * smoothness + offset.y * (1.0 - smoothness)

	if yaw_limit < 360:
		_yaw = clamp(_yaw, -yaw_limit - _total_yaw, yaw_limit - _total_yaw)
	if pitch_limit < 360:
		_pitch = clamp(_pitch, -pitch_limit - _total_pitch, pitch_limit - _total_pitch)
	_total_yaw += _yaw
	_total_pitch += _pitch
	
	rotate_y(deg_to_rad(-_yaw))
	rotate_object_local(Vector3(1,0,0), deg_to_rad(-_pitch))

func set_point_of_interest(ship, new_choose):
	point_of_interest = ship
	choose = new_choose
	if choose:
		set_privot(point_of_interest)
	else:
		set_privot(null)

func set_privot(value):
	privot = value
	if privot:
		distance = 25
	else:
		distance = 0
	distance_smooth = distance

func set_enabled(value):
	enabled = value
	#Input.set_mouse_mode(mouse_mode)
	set_process_input(enabled)
	set_physics_process(enabled)

func set_smoothness(value):
	smoothness = clamp(value, 0.001, 0.999)
